/*
 * Copyright (c) 2016-2021, Hangzhou Qulian Technology Co., Ltd.
 * Licensed under the Apache License, Version 2.0 (the "License");
 * you may not use this file except in compliance with the License.
 * You may obtain a copy of the License at
 *
 *    http://www.apache.org/licenses/LICENSE-2.0
 *
 * Unless required by applicable law or agreed to in writing, software
 * distributed under the License is distributed on an "AS IS" BASIS,
 * WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
 * See the License for the specific language governing permissions and
 * limitations under the License.
 */
#include <stdio.h>
#include "ohos_init.h"
#include "cmsis_os2.h"
#include "iot_gpio.h"
#include "iot_i2c.h"
#include "hi_i2c.h"
#include "iot_errno.h"
#include <hi_io.h>
#include <string.h>
#include <unistd.h>

#include "account.h"
#include "contract.h"
#include "keccak256.h"
#include "services.h"
#include "wifi_device.h"

#include "httpclient.h"

#include "discovery_service.h"
#include "ohos_types.h"
#include "lwip/sockets.h"
#include "lwip/inet.h"
#include "lwip/tcp.h"
#include "wifi_device.h"
#include "wifi_hotspot.h"


#define ALARM_ENABLE
// #define AHT_ENABLE

//only define one
#ifdef ALARM_ENABLE
#ifdef AHT_ENABLE
#undef AHT_ENABLE
#endif
#endif


#ifdef AHT_ENABLE
#define AHT20_BAUDRATE     400*1000
#define AHT_I2C_IDX        HI_I2C_IDX_0
#define AHT_DEVICE_ADDR    (0x38)
#define AHT_WRITE_ADDR     ((0x38<<1)|0x0)
#define AHT_READ_ADDR      ((0x38<<1)|0x1)

#define RETRY_TIMES         10

//init cmd
#define AHT_CMD_INIT      0xBE
#define AHT_CMD_MEASURE   0xAC
#define AHT_CMD_RESET     0xBA

//aht status check
#define AHT_CMD_STATUS    0x71

static long long timelong;
#endif


#define DEF_TIMEOUT 15
#define ONE_SECOND 100
#define LEVEL_ERROR (-1)
#define LEVEL_ONE 1
#define LEVEL_TWO 2
#define LEVEL_THREE 3
#define LEVEL_FOUR 4
#define DEF_TASK_STACK 2000
#define DEF_TASK_PRIORITY 20
#define TEST_SSID_COUNT 9

#define TEST_ASSERT_EQUAL_INT
#define TEST_ASSERT_NOT_EQUAL
#define TEST_ASSERT_TRUE

// 定义相关名称
const char *g_pkgName = "czy";
const char *g_sessionName = "czy";
const char *moduleName = "czy";

static int g_apEnableSuccess = 0;
static int g_staScanSuccess = 0;
WifiEvent g_wifiEventHandler = {0};


/**
 * callback task for wifi scan
 */
static void WifiScanStateTask(void)
{
    WifiScanInfo* info = malloc(sizeof(WifiScanInfo) * WIFI_SCAN_HOTSPOT_LIMIT);
    if (info == NULL) {
        printf("WifiScanStateTask:malloc fail.\n");
        return;
    }
    unsigned int checkSize = WIFI_SCAN_HOTSPOT_LIMIT;
    WifiErrorCode error = GetScanInfoList(info, &checkSize);
    if (error != WIFI_SUCCESS) {
        printf("WifiScanStateTask:get info fail, error is %d.\n", error);
    } else {
        printf("WifiScanStateTask:get scan size is %u.\n", checkSize);
        g_staScanSuccess = 1;
    }
    free(info);
    info = NULL;
}

/**
 * callback task for connection
 */
static volatile int g_connected = 0; 
static void WifiConnectionStateTask(void)
{
    WifiLinkedInfo linkInfo = {0};
    WifiErrorCode error = GetLinkedInfo(&linkInfo);
    if (error != WIFI_SUCCESS) {
        printf("WifiConnectionChanged:get link info fail, error is %d.\n", error);
        return;
    }
    if (linkInfo.connState != WIFI_CONNECTED) {
        printf("WifiConnectionChanged:connect fail!\n");
        return;
    }
    printf("WifiConnectionChanged:connect success.\n");
    g_connected = 1;
}

/**
 * callback function for hotspot
 */
static void HotspotStateTask(void)
{
    StationInfo info[WIFI_MAX_STA_NUM] = {0};
    unsigned int size = WIFI_MAX_STA_NUM;
    WifiErrorCode error = GetStationList(info, &size);
    if (error != WIFI_SUCCESS) {
        printf("HotspotStaJoin:get list fail, error is %d.\n", error);
        return;
    }
    printf("HotspotStaJoin:list size is %u.\n", size);
    g_apEnableSuccess++;
}

/**
 * callback function for wifi scan
 */
static void OnWifiScanStateChangedHandler(int state, int size)
{
    if (state != WIFI_STATE_AVALIABLE) {
        printf("ScanStateChanged:state is unavailable.\n");
    } else {
        printf("ScanStateChanged:state[%d], size[%d].\n", state, size);
        osThreadAttr_t attr;
        attr.name = "WifiScanStateTask";
        attr.attr_bits = 0U;
        attr.cb_mem = NULL;
        attr.cb_size = 0U;
        attr.stack_mem = NULL;
        attr.stack_size = DEF_TASK_STACK;
        attr.priority = DEF_TASK_PRIORITY;
        if (osThreadNew((osThreadFunc_t)WifiScanStateTask, NULL, &attr) == NULL) {
            printf("ScanStateChanged:create task fail!\n");
        }
    }
}

/**
 * callback function for wifi connection
 */
static void OnWifiConnectionChangedHandler(int state, WifiLinkedInfo* info)
{
    if (info == NULL) {
        printf("WifiConnectionChanged:info is null, stat is %d.\n", state);
    } else {
        osThreadAttr_t attr;
        attr.name = "WifiConnectionStateTask";
        attr.attr_bits = 0U;
        attr.cb_mem = NULL;
        attr.cb_size = 0U;
        attr.stack_mem = NULL;
        attr.stack_size = DEF_TASK_STACK;
        attr.priority = DEF_TASK_PRIORITY;
        if (osThreadNew((osThreadFunc_t)WifiConnectionStateTask, NULL, &attr) == NULL) {
            printf("WifiConnectionStateTask:create task fail!\n");
        }
    }
}

/**
 * callback function for STA join AP
 */
static void OnHotspotStaJoinHandler(StationInfo* info)
{
    if (info == NULL) {
        printf("HotspotStaJoin:info is null.\n");
    }  else {
        osThreadAttr_t attr;
        attr.name = "HotspotStateTask";
        attr.attr_bits = 0U;
        attr.cb_mem = NULL;
        attr.cb_size = 0U;
        attr.stack_mem = NULL;
        attr.stack_size = DEF_TASK_STACK;
        attr.priority = DEF_TASK_PRIORITY;
        if (osThreadNew((osThreadFunc_t)HotspotStateTask, NULL, &attr) == NULL) {
            printf("HotspotStaJoin:create task fail!\n");
        }
    }
}

/**
 * callback function for STA leave AP
 */
static void OnHotspotStaLeaveHandler(StationInfo* info)
{
    if (info == NULL) {
        printf("HotspotStaLeave:info is null.\n");
    } else {
        g_apEnableSuccess--;
    }
}

/**
 * callback function for AP
 */
static void OnHotspotStateChangedHandler(int state)
{
    printf("HotspotStateChanged:state is %d.\n", state);
}

static BOOL WifiServiceFuncTestSuiteSetUp(void)
{
    printf("WifiServiceFuncTestSuiteSetUp called\n");
    WifiErrorCode error;
    // check wifi stat
    int ret = IsWifiActive();
    if (ret == WIFI_STATE_AVALIABLE) {
        printf("[Setup]wifi is active, disable now...\n");
        error = DisableWifi();
        if (error == WIFI_SUCCESS) {
            printf("[Setup]disable wifi success\n");
        } else {
            TEST_ASSERT_EQUAL_INT(WIFI_SUCCESS, error);
            printf("[Setup]disable wifi fail, please disable wifi, then run test cases!\n");
            return FALSE;
        }
    }

    // check AP stat
    ret = IsHotspotActive();
    if (ret == WIFI_HOTSPOT_ACTIVE) {
        printf("[Setup]AP is active, disable now...\n");
        error = DisableHotspot();
        if (error == WIFI_SUCCESS) {
            printf("[Setup]disable AP success\n");
        } else {
            TEST_ASSERT_EQUAL_INT(WIFI_SUCCESS, error);
            printf("[Setup]disable AP fail, please disable ap, then run test cases!\n");
            return FALSE;
        }
    }

    // check device config
    WifiDeviceConfig config[WIFI_MAX_CONFIG_SIZE] = {0};
    unsigned int size = WIFI_MAX_CONFIG_SIZE;
    error = GetDeviceConfigs(config, &size);
    if (error != ERROR_WIFI_NOT_AVAILABLE) {
        printf("[Setup]there is device config, clear now...\n");
        int count = 0;
        for (int i = 0; i < WIFI_MAX_CONFIG_SIZE; i++) {
            if (&config[i] != NULL) {
                RemoveDevice(config[i].netId);
                count++;
            }
        }
        printf("[Setup]clear count [%d]\n", count);
    }

    // register wifi event
    g_wifiEventHandler.OnWifiScanStateChanged = OnWifiScanStateChangedHandler;
    g_wifiEventHandler.OnWifiConnectionChanged = OnWifiConnectionChangedHandler;
    g_wifiEventHandler.OnHotspotStaJoin = OnHotspotStaJoinHandler;
    g_wifiEventHandler.OnHotspotStaLeave = OnHotspotStaLeaveHandler;
    g_wifiEventHandler.OnHotspotStateChanged = OnHotspotStateChangedHandler;
    error = RegisterWifiEvent(&g_wifiEventHandler);
    TEST_ASSERT_EQUAL_INT(WIFI_SUCCESS, error);
    if (error != WIFI_SUCCESS) {
        printf("[Setup]register wifi event fail!\n");
        return FALSE;
    }
    return TRUE;
}



/**
 * @tc.number    : SUB_COMMUNICATION_WIFISERVICE_SDK_0300
 * @tc.name      : Test connect and disconnect interface
 * @tc.desc      : [C- SOFTWARE -0200]
 */
void connectWifi()
{
    usleep(3000000);
    printf("testConnectDisConnect is run\n");
    int netId = 0;
    WifiDeviceConfig config = {0};
    const char* ssid = "hyperchain";
    int ret = strncpy_s(config.ssid, WIFI_MAX_SSID_LEN, ssid, strlen(ssid));
    TEST_ASSERT_EQUAL_INT(WIFI_SUCCESS, ret);

    config.securityType = WIFI_SEC_TYPE_PSK;
    const char* pwd = "hyperch@1n";
    strncpy_s(config.preSharedKey, WIFI_MAX_KEY_LEN, pwd, strlen(pwd));

    WifiErrorCode error = AddDeviceConfig(&config, &netId);
    TEST_ASSERT_EQUAL_INT(WIFI_SUCCESS, error);
    printf("AddDeviceConfig success\n");
    error = ConnectTo(netId);
    printf("errtype %d\n", error);
    while (!g_connected) { // wait until connect to AP
        osDelay(10);
    }
    printf("connected!!!!!!!!\n");
    struct netif* g_iface = netifapi_netif_find("wlan0");
    if (g_iface) {
        err_t ret = 0;
        char* hostname = "hispark";
        ret = netifapi_set_hostname(g_iface, hostname, strlen(hostname));
        printf("netifapi_set_hostname: %d\r\n", ret);

        ret = netifapi_dhcp_start(g_iface);
        printf("netifapi_dhcp_start: %d\r\n", ret);

        while(1){
            osDelay(100); // wait DHCP server give me IP
            // ret = netifapi_netif_common(g_iface, dhcp_clients_info_show, NULL);
            // printf("netifapi_netif_common: %d\r\n", ret);
            ip4_addr_t ip = {0};
            ip4_addr_t netmask = {0};
            ip4_addr_t gw = {0};
            ret = netifapi_netif_get_addr(g_iface, &ip, &netmask, &gw);
            if (ret == ERR_OK) {
                printf("---------------------\n");
                printf("ip = %s\r\n", ip4addr_ntoa(&ip));
                printf("---------------------\n");
                printf("netmask = %s\r\n", ip4addr_ntoa(&netmask));
                printf("gw = %s\r\n", ip4addr_ntoa(&gw));
            }
            printf("netifapi_netif_get_addr: %d\r\n", ret);
            if(strcmp(ip4addr_ntoa(&ip),"0.0.0.0")!=0){
                break;
            }
        }
    }else{
        printf("netifapi_netif_find failed\n");
    }
    
    TEST_ASSERT_EQUAL_INT(WIFI_SUCCESS, error);

    //TEST_ASSERT_NOT_EQUAL(WIFI_SUCCESS, error);
    // unsigned char mac[WIFI_MAC_LEN];
    // error = GetDeviceMacAddress((unsigned char *)mac);
    // TEST_ASSERT_EQUAL_INT(WIFI_SUCCESS, error);
    printf("-----\n");
    //CommTcpClientTask();

    // error = Disconnect();
    // TEST_ASSERT_NOT_EQUAL(WIFI_SUCCESS, error);
    // error = RemoveDevice(netId);
    // TEST_ASSERT_EQUAL_INT(WIFI_SUCCESS, error);
}

void onSuccess(int publishId)
{
    printf("publish succeeded, publishId = %d\r\n", publishId);
}

void onFail(int publishId, PublishFailReason reason)
{
    printf("publish failed, publishId = %d, reason = %d\r\n", publishId, reason);
}


static void CommTcpClientTask2(char* ip, unsigned int port, char* rawMsg, unsigned int rawMsgLen)
{
    printf("start CommTcpClientTask2\n");
    httpclient_t client = { 0 };
	httpclient_data_t client_data = { 0 };
	char buf[1024];
	memset(buf, 0, sizeof(buf));
	client_data.response_buf = buf;
	client.timeout_in_sec = 20;
	client_data.response_buf_len = 1024;
    client_data.post_buf = rawMsg;
    client_data.post_buf_len = rawMsgLen;
    client_data.post_content_type = "application/json";
	printf("Data received: %d, %s\r\n",
			oc_httpclient_post(&client, "http://8.136.20.47:8081/", &client_data),
			client_data.response_buf);
    printf("end CommTcpClientTask2\n");
    
}

static void SocketClientTask(char *ipaddr, int sockport, char* rawMsg, unsigned int rawMsgLen) {
    int client_sockfd;
    int len;
    struct sockaddr_in remota_addr; //Server - side network address structure
    char buf[1024];  //Buffer for data transfer
    memset(&remota_addr,0,sizeof(remota_addr)); //Data initialization - clear zero
    remota_addr.sin_family = AF_INET;  //Set it to IPV4 communication
    remota_addr.sin_addr.s_addr = inet_addr(ipaddr);
    remota_addr.sin_port = htons(sockport); //Server port number
    
    // Create a client socket --Ipv4, connection-oriented communication, TCP
    // Returns 0 on success, -1 on failure
    if ((client_sockfd=socket(PF_INET, SOCK_STREAM, 0))<0) {
        printf("socket to err\n");
        return ;
    }
    
    //Binds the socket to the server's network address
    if (connect(client_sockfd, (struct sockaddr *)&remota_addr, sizeof(struct sockaddr))<0) {
        printf("connect %s:%d err\n", ipaddr, sockport);
        close(client_sockfd);
        return ;
    }
    memset(buf, 0, sizeof(buf));
    memcpy(buf, rawMsg, rawMsgLen);
    len = send(client_sockfd,buf,strlen(buf),0);
    if(len < 0)printf("socket send err-----------------\n");
    close(client_sockfd);
}

#ifdef AHT_ENABLE
unsigned int ahtRead(unsigned char* data, unsigned int datalen) {
    unsigned int ret = IoTI2cRead(AHT_I2C_IDX, AHT_READ_ADDR, data, datalen);
    if(ret != IOT_SUCCESS) {
        printf("AHT_READ failed\n");
    }
    return ret;
}

unsigned int ahtWrite(unsigned char* data, unsigned int dataLen) {
    unsigned int ret = 0;
    ret = IoTI2cWrite(AHT_I2C_IDX, AHT_WRITE_ADDR, data, dataLen);
    if(ret != IOT_SUCCESS) {
        printf("AHT_WRITE failed\n");
    }
    return ret;
}

unsigned int ahtStatusCmd(void) {
    unsigned char cmd[] = {AHT_CMD_STATUS};
    return ahtWrite(cmd, sizeof(cmd));
}

unsigned char ahtReadStatus(void) {
    unsigned int ret = ahtStatusCmd();
    if(ret != IOT_SUCCESS){
        printf("aht status check err\n");
        return 0xff;
    }

    unsigned char buf[6];
    memset(buf, 0, sizeof(buf));
    ret = ahtRead(buf, sizeof(buf));
    if(ret != IOT_SUCCESS){
        printf("aht read status err\n");
        return 0xff;
    } else {
        printf("status:%#x\n", buf[0]);
    }
    return buf[0];
}

unsigned int ahtInit(void) {
    unsigned char cmd[] = {AHT_CMD_INIT, 0x08, 0x00};
    return ahtWrite(cmd, sizeof(cmd));
}

unsigned int ahtReset(void) {
    unsigned char cmd[] = {AHT_CMD_RESET};
    return ahtWrite(cmd, sizeof(cmd));
}

unsigned int ahtStartMeasure(void) {
    unsigned char cmd[] = {AHT_CMD_MEASURE, 0x33, 0x00};
    return ahtWrite(cmd, sizeof(cmd));
}

unsigned int ahtMeasure(double *outHumi, double *outTemp) {
    if(outHumi == NULL || outTemp == NULL)return IOT_FAILURE;
    unsigned char buf[6];
    memset(buf, 0, sizeof(buf));
    
    //send cmd and start to measure
    unsigned int ret = ahtStartMeasure();
    if(ret != IOT_SUCCESS) {
        printf("start measure failed\n");
        return ret;
    }
    usleep(100*1000);
    
    //read status 
    ret = ahtRead(buf, sizeof(buf));
    if(ret != IOT_SUCCESS) {
        printf("aht read failed\n");
        return ret;
    }
    unsigned int i = 0;
    while((buf[0] & 0x80 == 0x80) && i++ < RETRY_TIMES) {
        printf("measure now, please waiting......\n");
        usleep(100*1000);
        ret = ahtRead(buf, sizeof(buf));
        if(ret != IOT_SUCCESS) {
            printf("aht read failed\n");
            return ret;
        }
    }

    if(i >= RETRY_TIMES) {
        printf("measure failed\n");
        return IOT_FAILURE;
    }
    unsigned int humiRaw = buf[1];
    humiRaw = (humiRaw << 8) | buf[2];
    humiRaw = (humiRaw << 4) | ((buf[3] >> 4) & 0x0f);
    double humi = humiRaw * 100.0 / (1<<20);

    unsigned int tempRaw = buf[3]&0x0f;
    tempRaw = (tempRaw << 8) | buf[4];
    tempRaw = (tempRaw << 8) | buf[5];
    double temp = tempRaw * 200.0 / (1<<20) - 50;
    printf("---raw h:%d---raw t:%d---h:%llf---t:%llf;---\n", humiRaw, tempRaw, humi, temp);
    *outHumi = humi;
    *outTemp = temp;
    return IOT_SUCCESS;
}

void ahtHardwareInit() {
    //init gpio
    unsigned int ret = IoTGpioInit(HI_IO_NAME_GPIO_13);
    if(ret != IOT_SUCCESS)printf("gpio init err\n");
    ret = IoTGpioInit(HI_IO_NAME_GPIO_14);
    if(ret != IOT_SUCCESS)printf("gpio init err\n");
    //remap i2c
    hi_io_set_func(HI_IO_NAME_GPIO_13, HI_IO_FUNC_GPIO_13_I2C0_SDA); 
    hi_io_set_func(HI_IO_NAME_GPIO_14, HI_IO_FUNC_GPIO_14_I2C0_SCL); 
    //init i2c
    ret = IoTI2cInit(AHT_I2C_IDX, AHT20_BAUDRATE);
    if(ret != IOT_SUCCESS)printf("i2c init err\n");
    //sleep until start
    usleep(40*1000);
    unsigned char status = ahtReadStatus();

    if((0x08 & status != 0x08) || (0x80 & status == 0x80)) {
        ret = ahtReset();
        if(ret != IOT_SUCCESS)printf("aht reset failed\n");
        usleep(20*1000);
        ret = ahtInit();
        usleep(40*1000);
        if(ret != IOT_SUCCESS)printf("ahtInit failed\n");
    }
    //check again
    usleep(40*1000);
    status = ahtReadStatus();
    printf("aht init end\n");
}
#endif

void wifi_init(void)
{
    //Initialize the soft bus
    printf("enter SoftBus Task\r\n");
    WifiServiceFuncTestSuiteSetUp();
    WifiErrorCode error = EnableWifi();
    TEST_ASSERT_EQUAL_INT(WIFI_SUCCESS, error);
    connectWifi();
}

#ifdef AHT_ENABLE
static long long stringToLong(char* str)
{
    int n = strlen(str);
    long long res = 0;
    int i;
    for(i = 0; i < n; i++)
        res = res*10 + str[i]-'0';
    return res;
}
void setCurrentTime()
{
	httpclient_t client = { 0 };
	httpclient_data_t client_data = { 0 };
	char buf[256];
	memset(buf, 0, sizeof(buf));
	client_data.response_buf = buf;
	client.timeout_in_sec = 20;
	client_data.response_buf_len = 256;
	printf("Data received: %d, %s\r\n",
			oc_httpclient_get(&client, "http://api.m.taobao.com/rest/api3.do?api=mtop.common.getTimestamp", &client_data),
			client_data.response_buf);
    cJSON* items = cJSON_Parse((char*)client_data.response_buf);
    cJSON*  data = cJSON_GetObjectItem(items, "data");
    char* timestring = cJSON_GetObjectItem(data, "t")->valuestring;
    timelong = stringToLong(timestring);
    printf("timelong %lld\n",timelong);

    cJSON_Delete(items);
}
#endif

#ifdef ALARM_ENABLE
void oledInit() {
    unsigned int ret = IoTGpioInit(HI_IO_NAME_GPIO_11);
    if(ret != IOT_SUCCESS)printf("gpio init err\n");
    ret = IoTGpioInit(HI_IO_NAME_GPIO_12);
    if(ret != IOT_SUCCESS)printf("gpio init err\n");
    
     hi_io_set_func(HI_IO_NAME_GPIO_11, HI_IO_FUNC_GPIO_11_GPIO); 
    hi_io_set_func(HI_IO_NAME_GPIO_12, HI_IO_FUNC_GPIO_12_GPIO); 

    IoTGpioSetDir(HI_IO_NAME_GPIO_11, IOT_GPIO_DIR_OUT);
    IoTGpioSetDir(HI_IO_NAME_GPIO_12, IOT_GPIO_DIR_OUT);


    for (int i = 0; i < 1; i++) {
        for (unsigned int j = 0; j < 3; j++) {
            printf("on\n");
            IoTGpioSetOutputVal(HI_IO_NAME_GPIO_11, 1);
            usleep(1000*1000);
            printf("off\n");
            IoTGpioSetOutputVal(HI_IO_NAME_GPIO_11, 0);
            usleep(1000*1000);
        }
    }
}
#endif 

void globalInit(void) {
#ifdef ALARM_ENABLE
    oledInit();
#endif

#ifdef AHT_ENABLE
    ahtHardwareInit();
#endif

    //init wifi
    wifi_init();

#ifdef AHT_ENABLE
    setCurrentTime();
#endif
}

#ifdef AHT_ENABLE
void qlInit(account_t * my_account, abi_t *abiroot) {
    ql_byte_t acc_json[] = "{\"address\":\"8399b2b7e104cebb8b8938a2c79e26cb4733b0b5\",\"algo\":\"0x03\",\"version\":\"4.0\",\"publicKey\":\"049c660da3c16fd0df820b747d82344916db69d7553d2456323c820f1b1f4f225986d1f16cde06d99d94aa8998f0a14b6aeca21d7cad7670516cc911e4b035f9e5\",\"privateKey\":\"8747be107feb7959f4e8c8936a31aac5ffd4ed4d62d0e9edee2854531e62ea5e\"}";
    ql_err_t err = AccountInitJson(my_account, acc_json);
    if(err != ACCOUNT_SUCCESS) {
        printf("account_new failed : %d", err);
    }
    printf("account:%s\n", my_account->addr);
    char buf[] = "[{\"anonymous\":false,\"inputs\":[{\"indexed\":true,\"internalType\":\"address\",\"name\":\"from\",\"type\":\"address\"},{\"indexed\":false,\"internalType\":\"string\",\"name\":\"info\",\"type\":\"string\"}],\"name\":\"AlarmEvent\",\"type\":\"event\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"_data\",\"type\":\"uint256\"}],\"name\":\"setThreshold\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"},{\"inputs\":[{\"internalType\":\"uint256\",\"name\":\"t\",\"type\":\"uint256\"},{\"internalType\":\"uint256\",\"name\":\"h\",\"type\":\"uint256\"}],\"name\":\"uploadInfo\",\"outputs\":[],\"stateMutability\":\"nonpayable\",\"type\":\"function\"}]";
    err = AbiInitFromString(abiroot, buf);
    if(err != CONTRACT_SUCCESS)printf("abi init err\n");
    else printf("abi succeed\n");
}

void setTimestamp(long long *dst) {
    struct timeval t;
    gettimeofday(&t,NULL);
    *dst = (long long)(t.tv_sec+timelong/1000) * 1000000000 + (long long)(t.tv_usec+timelong % 1000 * 1000)*1000; // ns
    
}
#endif

#ifdef ALARM_ENABLE
static int startSocketServer(void) {
    int tcp_server_sockfd;
    struct sockaddr_in address; 
    /* create a TCP socket */ 
    if ((tcp_server_sockfd = socket(AF_INET, SOCK_STREAM, 0)) < 0) { 
        printf("[Error] can not create socket\n"); 
        return; 
    } 
    /* bind to port 80 at any inteRFace */ 
    address.sin_family = AF_INET; 
    address.sin_port = htons(80); 
    address.sin_addr.s_addr = INADDR_ANY; 

    if (bind(tcp_server_sockfd, (struct sockaddr *)&address, sizeof(address)) < 0) { 
        printf("[Error] can't bind socket\n"); 
        close(tcp_server_sockfd); 
        return; 
    } 

    /* listen for connections (TCP listen backlog = 1) */ 
    listen(tcp_server_sockfd, 1);
    return tcp_server_sockfd;
}

void url_handler(int client, char *recv_buffer) {
    printf("recv msg |%s| from client %d\n", recv_buffer, client);
    cJSON *items = cJSON_Parse(recv_buffer);
    if(items == NULL) {
        printf("format err\n");
        return;
    } 
    printf("item type:%d\n", items->type);
    cJSON *event = cJSON_GetObjectItem(items, "event");
    cJSON *deviceAddr = cJSON_GetObjectItem(items, "deviceAddress");
    if(event == NULL){
	    printf("event is NULL\n");
	    return;
    }
    else if(event->type != cJSON_String)printf("event type != string;type is %d\n", event->type);
    else if(event->valuestring == NULL)printf("event value is NULL\n");
     printf("event->value:%s\n", event->valuestring);
    if(event->valuestring) {
        if(!strcmp(event->valuestring, "alarm")) {
            printf("--------------------alarm------------------\n");
            for (int i = 0; i < 1; i++) {
                for (unsigned int j = 0; j < 3; j++) {
                    printf("on\n");
                    IoTGpioSetOutputVal(HI_IO_NAME_GPIO_11, 1);
                    usleep(1000*1000);
                    printf("off\n");
                    IoTGpioSetOutputVal(HI_IO_NAME_GPIO_11, 0);
                    usleep(1000*1000);
                }
            }
        }else {
            printf("--------------------notalarm------------------\n");
        }
    }
    if(deviceAddr &&  deviceAddr->valuestring) {
    	char Addr[1024];
        memset(Addr, 0, sizeof(Addr));
        memcpy(Addr, deviceAddr->valuestring, strlen(deviceAddr->valuestring));
        printf("deviceAddr:%s\n", Addr);
    }
    cJSON_Delete(items);
}
#endif

#ifdef ALARM_ENABLE
void alarmTask() {
    struct sockaddr_in remotehost;
    globalInit();
    int server_sockfd = startSocketServer();

    while(1) {
    	int client;
        //listen 
        int size = sizeof(remotehost);
        client = accept(server_sockfd, (struct sockaddr *)&remotehost, (socklen_t *)&size); 
        if (client >= 0) { 
            int buflen = 1024; 
            int ret; 
            unsigned char recv_buffer[1024]; 
            memset(recv_buffer, 0, sizeof(recv_buffer));
            
            /* Read in the request */ 
            ret = read(client, recv_buffer, buflen); 
            if (ret <= 0) { 
                close(client); 
                printf("[Error] read failed\r\n"); 
                continue; 
            } 
            
            url_handler(client, (char*)recv_buffer); 
            
            /* Close connection client */ 
            close(client); 
        } else { 
            close(client); 
        } 
    }
}
#endif

#ifdef AHT_ENABLE
int ahtTask() {
    printf("run ahtTask\n");
    ql_err_t err;
    account_t my_account;
    abi_t *abiroot = CreateAbi();
    //init account and abiroot
    qlInit(&my_account, abiroot);
    contract_t con;

    globalInit();
    
    int cnt = 0;
    while(1) {
        double humi = 0;
        double temp = 0;
        //get humi and temp
        usleep(15*1000*1000);
        unsigned int ret = ahtMeasure(&humi, &temp);
        if(ret != IOT_SUCCESS)printf("measure failed\n");
        //invoke evm and send 
        err = ContractInit(&con, my_account.addr, "", "");
        if(err != CONTRACT_SUCCESS)printf("con init err\n");
        arg_t *args = CreateArg();
        AddIntArg(args, (ql_uint64_t)temp);
        AddIntArg(args, (ql_uint64_t)humi);
        err = InvokeEVM(&con, "0xdf498494e3b24734375973dd4dbfacf05018316c", "uploadInfo(uint256,uint256)", abiroot, args);
        if(err != CONTRACT_SUCCESS)printf("invoke err\n");
        setTimestamp(&con.timestamp);
        err = SetSignature(&con, my_account);
        if(err != CONTRACT_SUCCESS)printf("signature err\n");
        char *rawMsg = hpcAdapter("contract_invokeContract", con.from, con.to, con.value, con.payload, con.timestamp, con.nonce, con.extra, con.extraid, con.signature);
        printf("send_str:");
        int len = strlen(rawMsg);
        int i;
        for(i = 0; i< len; i++)
            printf("%c",rawMsg[i]);
        printf("\n---------\n");
        char ipaddr[] = "10.1.19.101";//rsp ip addr
        // char ipaddr[] = "10.1.19.84";//local test ip addr
        int sockport = 8080;//rsp port
        // CommTcpClientTask("10.1.19.206", 8081, rawMsg, strlen(rawMsg));
        // CommTcpClientTask2("8.136.20.47", 8080, rawMsg, strlen(rawMsg));
        // CommTcpClientTask2("10.1.19.84", 8080, rawMsg, strlen(rawMsg));
        SocketClientTask(ipaddr, sockport, rawMsg, strlen(rawMsg));
        CleanContract(&con);
        ArgFree(args);

    }
    // abi_free(abiroot);
}
#endif

#ifdef AHT_ENABLE
SYS_SERVICE_INIT_PRI(ahtTask,3);
#endif

#ifdef ALARM_ENABLE
SYS_SERVICE_INIT_PRI(alarmTask,3);
#endif
